package com.gujh.security.authentication.sms;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.Setter;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;

@Getter
@Setter
public class SmsAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login/sms");

    private String phoneParameter = "phone";

    private String smsCodeParameter = "code";

    protected SmsAuthenticationFilter() {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        if (!request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        JSONObject jsonParam = JSONUtil.parseObj(request.getInputStream());
        String phone = jsonParam.getStr(getPhoneParameter(), "");
        String code = jsonParam.getStr(getSmsCodeParameter(), "");
        SmsAuthenticationToken unauthenticated = SmsAuthenticationToken.unauthenticated(phone, code);
        unauthenticated.setDetails(this.authenticationDetailsSource.buildDetails(request));
        return super.getAuthenticationManager().authenticate(unauthenticated);
    }
}
